home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dlink / jump.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-09  |  4.0 KB  |  159 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  JUMP.C
  9.  *
  10.  *  Deal with making a jump table to handle PC-relative code >+/-32K rel offset.
  11.  *
  12.  *  Consider only HUNK_CODE lists
  13.  */
  14.  
  15. #include "defs.h"
  16.  
  17. Prototype int    HandleJumpTable(List *);
  18. Prototype int    HunkExtSymJUMP(Hunk *, ubyte, ulong, ulong *);
  19.  
  20. int
  21. HandleJumpTable(list)
  22. List *list;
  23. {
  24.     HunkListNode *hl;
  25.     Hunk *hunk;
  26.     int hadToAddTable = 0;
  27.  
  28.     for (hl = GetHead(list); hl; hl = GetSucc(&hl->Node)) {
  29.     if (hl->Node.ln_Type != NT_CODE)
  30.         continue;
  31.     for (hunk = GetHead(&hl->HunkList); hunk; hunk = GetSucc(&hunk->Node)) {
  32.         dbprintf(4, ("jump hunk %08lx %s\n", hunk, HunkToStr(hunk)));
  33.         hadToAddTable += ScanHunkExt(hunk, SCAN_RELOC_JUMP);
  34.     }
  35.     }
  36.     return(hadToAddTable);
  37. }
  38.  
  39.  
  40. /*
  41.  *  JUMP
  42.  *
  43.  *  This routine returns a dummy 0 always.  This routine checks 16 bit PC-rel
  44.  *  relocations for validity.  Any failures force a jump table hunk to be added
  45.  *  after this hunk with the PC-Rel symbol redirected to it.  The symbol name
  46.  *  is changed to:
  47.  *            %xxx    where xxx is a unique identifier.
  48.  *
  49.  *  And said symbol is created under the new hunk.
  50.  */
  51.  
  52. int
  53. HunkExtSymJUMP(Hunk *hunk, ubyte type, ulong len, ulong *scan)
  54. {
  55.     Sym *sym;
  56.     Hunk *destHunk;
  57.     long n;
  58.     ulong *newScan;
  59.     short didJmp = 0;
  60.  
  61.     /*
  62.      *    ignore other types and only deal with resolved relocations.  Only deal
  63.      *    with PC-rel refs to a standard XDEF.
  64.      *
  65.      *    Any PC-rel refs that are either out of range or to a differently named
  66.      *    hunk are changed to jump table entries.  If we are forced to change
  67.      *    one rel call to a jump table we change them all
  68.      */
  69.  
  70.     if (type != 131)
  71.     return(0);
  72.     if ((sym = FindSymbol(scan, len)) == NULL || (destHunk = sym->Hunk) == NULL || sym->Type != 1)
  73.     return(0);
  74.     if (destHunk->Node.ln_Type != NT_CODE) {
  75.     if (AbsWordOpt == 0) {
  76.         cerror(EERROR_PCREL_RELOC_TO_DATA,
  77.         hunk->Module->Node.ln_Name, hunk->Node.ln_Name,
  78.         sym->SymLen, sym->SymName
  79.         );
  80.     }
  81.     return(0);
  82.     }
  83.  
  84.     if (destHunk->HX != hunk->HL)
  85.     didJmp = 1;
  86.  
  87.     newScan = scan + len;
  88.  
  89.     if (didJmp == 0 && (n = FromMsbOrder(*newScan))) {
  90.     char *dbase = (char *)hunk->Data;
  91.  
  92.     for (++newScan; n--; ++newScan) {
  93.         ulong doff = FromMsbOrder(*newScan);
  94.         long pcrel;
  95.         uword dcontents = FromMsbOrderShort(*(uword *)(dbase + doff));
  96.  
  97.         if (dcontents) {    /*  XXX  */
  98.         dbprintf(0, ("DCONTENTS != 0 in PC-Rel access\n"));
  99.         return(0);
  100.         }
  101.  
  102.         pcrel = (destHunk->Offset + sym->Value + dcontents) - (hunk->Offset + doff);
  103.         if (pcrel < -32768 || pcrel > 32767) {
  104.         if (hunk == destHunk)
  105.             cerror(EFATAL_PC_REL_RANGE);
  106.         didJmp = 1;
  107.         break;
  108.         }
  109.     }
  110.     }
  111.     if (didJmp == 0)
  112.     return(0);
  113.  
  114.     /*
  115.      *    Create Jump Table Entry.
  116.      *
  117.      *    (1) manually relocate PC-relative jumps
  118.      *    (2) change symbol from ext_ref16 to <reserved> and modify offsets
  119.      *        to beyond end of data (table created in final phase).
  120.      */
  121.  
  122.     dbprintf(0, ("Gen Jump Table %s to symbol %.*s\n", HunkToStr(hunk), sym->SymLen, sym->SymName));
  123.  
  124.     newScan = scan + len;
  125.     n = FromMsbOrder(*newScan);
  126.  
  127.     for (++newScan; n--; ++newScan) {
  128.     ulong doff = FromMsbOrder(*newScan);    /*  offset in hunk  */
  129.     long  rv = hunk->TotalBytes - doff;
  130.  
  131.     if (rv < -32768 || rv > 32767)
  132.         cerror(EFATAL_PC_REL_RANGE);
  133.  
  134.     if (doff > hunk->Bytes - 2)
  135.         cerror(EFATAL_RANGE_HUNK, HunkToStr(hunk), doff);
  136.     else
  137.         *(short *)((char *)hunk->Data + doff) = ToMsbOrderShort(rv);
  138.  
  139.     /*
  140.      * change to jump table entry
  141.      */
  142.  
  143.     *newScan = ToMsbOrder(hunk->TotalBytes + 2);
  144.     }
  145.     {
  146.     int n = hunk->TotalBytes - hunk->Bytes;
  147.  
  148.     hunk->JmpData = realloc(hunk->JmpData, n + 8);
  149.     if (hunk->JmpData == NULL)
  150.         NoMemory();
  151.     setmem((char *)hunk->JmpData + n, 8, 0);
  152.     *(uword *)((char *)hunk->JmpData + n) = ToMsbOrderShort(0x4EF9);
  153.     }
  154.     scan[-1] = ToMsbOrder((FromMsbOrder(scan[-1]) & 0x00FFFFFF) | (RESERVED_PCJMP_TYPE << 24));
  155.     hunk->TotalBytes += 6;          /*  'allocate' space for jmp  */
  156.     return(1);
  157. }
  158.  
  159.